#include "Student.h"

Student::Student( Printer &prt, NameServer &nameServer, 
		 		  WATCardOffice &cardOffice, unsigned int id,
		 		  unsigned int maxPurchases ) :
myPrinter(prt), myNameServer(nameServer), myCardOffice(cardOffice)
{
	myID = id;
	myMaxPurchases = maxPurchases;
	myWatCard = NULL;
	myValidateCard = true;
}

Student::~Student()
{
	// dummy destruction
}

void Student::main()
{
	Student* This = this;
	try
	{
		// create a WATCard
		myFatCard = myCardOffice.create(myID, 5, myWatCard);
		unsigned int num_purchases = Global::prng(1, myMaxPurchases);
		myFavouriteDrink = (VendingMachine::Flavours)
							Global::prng(0, VendingMachine::FLAVOUR_SIZE-1);

		myPrinter.print(Printer::Student, myID, 'S', 
						(int)myFavouriteDrink, num_purchases);
		
		// get a vendingmachine for me
		myVendingMachine = myNameServer.getMachine(myID);
		myPrinter.print(Printer::Student, myID, 'V', 
						myVendingMachine->getId());

		for(unsigned int d=0; d<num_purchases; d++)
		{
			// yield for a certain number of times
			unsigned int class_period = Global::prng(1, 10);
			yield(class_period);	

			_Enable 
			{
				// synchronize, make sure the watcard is there.
				myValidateCard = true;
				while(myValidateCard)
				{
					myValidateCard = false;
					myFatCard();
				}
			} // enable

			VendingMachine::Status buy_status = 
			myVendingMachine->buy(myFavouriteDrink, *myWatCard);

			switch(buy_status)
			{
				case VendingMachine::BUY :
				{
					// drink the bottle .. glub glub glub ...
					myPrinter.print(Printer::Student, myID, 'B',
									(*myFatCard()).getBalance());
					break;
				}
				case VendingMachine::STOCK :
				{
					// machine is out of stock, get a new vending machine
					myVendingMachine = myNameServer.getMachine(myID);

					myPrinter.print(Printer::Student, myID, 'V', 
									myVendingMachine->getId());
					d -= 1;
					break;
				}
				case VendingMachine::FUNDS :
				{
					// not enough money, transfer some money
					unsigned int amount = 5 + myVendingMachine->cost();
					myFatCard = myCardOffice.transfer(myID, 
													  amount, 
													  myWatCard);
					// we didn't get the drink, so decrement 1 
					d -= 1;
					break;
				}
				default:
					break;
			} // switch
		} // for
	}// try
	_CatchResume( WATCardOffice::Lost e) (Student* This)
	{
		// do something here
		This->myPrinter.print(Printer::Student, This->myID, 'L');
		if(This->myWatCard) delete This->myWatCard;
		This->myWatCard = NULL;
		This->myFatCard = This->myCardOffice.create(This->myID, 5, This->myWatCard);

		This->myValidateCard = true;
	}

	myPrinter.print(Printer::Student, myID, 'F');

	if(myWatCard) delete myWatCard;
}
